//数字千分位分隔
export const format = (n: number): string => {
  const num = n.toString();
  const len = num.length;

  if (len <= 3) {
    return num;
  } else {
    let temp = '';
    const remainder = len % 3;

    if (remainder > 0) { // 不是3的整数倍
      return num.slice(0, remainder) + ',' + num.slice(remainder).match(/\d{3}/g)?.join(',') + temp;
    } else { // 3的整数倍
      return num.match(/\d{3}/g)?.join(',') || '';
    }
  }
}



//全角转换为半角
export const toCDB = (str: string): string => {
  let result: string = "";
  for (let i = 0; i < str.length; i++) {
    const code = str.charCodeAt(i);
    if (code >= 65281 && code <= 65374) {
      result += String.fromCharCode(str.charCodeAt(i) - 65248);
    } else if (code == 12288) {
      result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
    } else {
      result += str.charAt(i);
    }
  }
  return result;
}


//半角转换为全角
export const toDBC = (str: string): string => {
  let result = "";
  for (let i = 0; i < str.length; i++) {
    const code = str.charCodeAt(i);
    if (code >= 33 && code <= 126) {
      result += String.fromCharCode(str.charCodeAt(i) + 65248);
    } else if (code == 32) {
      result += String.fromCharCode(str.charCodeAt(i) + 12288 - 32);
    } else {
      result += str.charAt(i);
    }
  }
  return result;
}


//数字转化为中文数字
export const intToChinese = (value: string): string => {
  const str: string = String(value);
  const len: number = str.length - 1;
  const idxs: string[] = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '亿'];
  const num = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  return str.replace(/([1-9]|0+)/g, ($, $1, idx, full) => {
    let pos = 0;
    if ($1[0] !== '0') {
      pos = len - idx;
      if (idx == 0 && $1[0] == 1 && idxs[len - idx] == '十') {
        return idxs[len - idx];
      }
      return num[$1[0]] + idxs[len - idx];
    } else {
      let left = len - idx;
      let right = len - idx + $1.length;
      if (Math.floor(right / 4) - Math.floor(left / 4) > 0) {
        pos = left - left % 4;
      }
      if (pos) {
        return idxs[pos] + num[$1[0]];
      } else if (idx + $1.length >= len) {
        return '';
      } else {
        return num[$1[0]]
      }
    }
  });
}

//存储sessionStorage
export const sessionStorageSet = (key: string, value: string) => {
  if (!key) return;
  if (typeof value !== 'string') {
    value = JSON.stringify(value);
  }
  window.sessionStorage.setItem(key, value)
};

//获取sessionStorage
export const sessionStorageGet = (key: string) => {
  if (!key) return;
  return window.sessionStorage.getItem(key)
};

//删除sessionStorage
export const sessionStorageRemove = (key: string) => {
  if (!key) return;
  window.sessionStorage.removeItem(key)
};

//删除cookie
export const delCookie = (key: string) => {
  document.cookie = `${encodeURIComponent(key)}=;expires=${new Date()}`
};

//校验是否为中国大陆的邮政编码
export const isPostCode = (value: string): boolean => {
  return /^[1-9][0-9]{5}$/.test(value.toString());
}

//校验是否为IPv6地址
export const isIPv6 = (str: string): boolean => {
  const match = str.match(/:/g);
  const hasDoubleColon = /::/.test(str);

  if (match) {
    const length = match.length;
    if (length <= 7 && hasDoubleColon) {
      return /^([\da-f]{1,4}(:|::)){1,6}[\da-f]{1,4}$/i.test(str);
    } else if (length === 7) {
      return /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i.test(str);
    }
  }
  return false;
};



//校验是否为邮箱地址
export const isEmail = (value: string): boolean => {
  return /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value);
}

//校验是否为中国大陆手机号
export const isTel = (value: number): boolean => {
  return /^1[3,4,5,6,7,8,9][0-9]{9}$/.test(value.toString());
}

//校验是否包含emoji表情
export const isEmojiCharacter = (value: string): boolean => {
  value = String(value);
  for (let i = 0; i < value.length; i++) {
    const hs = value.charCodeAt(i);
    if (0xd800 <= hs && hs <= 0xdbff) {
      if (value.length > 1) {
        const ls = value.charCodeAt(i + 1);
        const uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
        if (0x1d000 <= uc && uc <= 0x1f77f) {
          return true;
        }
      }
    } else if (value.length > 1) {
      const ls = value.charCodeAt(i + 1);
      if (ls == 0x20e3) {
        return true;
      }
    } else {
      if (0x2100 <= hs && hs <= 0x27ff) {
        return true;
      } else if (0x2B05 <= hs && hs <= 0x2b07) {
        return true;
      } else if (0x2934 <= hs && hs <= 0x2935) {
        return true;
      } else if (0x3297 <= hs && hs <= 0x3299) {
        return true;
      } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030
        || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b
        || hs == 0x2b50) {
        return true;
      }
    }
  }
  return false;
}

//检测URL是否有效
export const getUrlState = (URL: string): boolean => {
  let xmlhttp = new ActiveXObject("microsoft.xmlhttp");
  xmlhttp.Open("GET", URL, false);
  try {
    xmlhttp.Send();
  } catch (e) {
  } finally {
    let result = xmlhttp.responseText;
    if (result) {
      if (xmlhttp.Status == 200) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
}

//修改URL中的参数
export const replaceParamVal = (paramName: string, replaceWith: string): string => {
  const oUrl = location.href.toString();
  const re = new RegExp(`(${paramName}=)([^&]*)`, 'gi');
  const newUrl = oUrl.replace(re, `${paramName}=${encodeURIComponent(replaceWith)}`);
  location.href = newUrl;
  return newUrl;
};


//删除URL中指定参数
export const funcUrlDel = (name: string): string | undefined => {
  const baseUrl = `${location.origin}${location.pathname}?`;
  const query = location.search.substring(1);

  if (query.includes(name)) {
    const params: Record<string, string> = {};
    const arr = query.split("&");

    for (const param of arr) {
      const [key, value] = param.split("=");
      if (key) {
        params[decodeURIComponent(key)] = decodeURIComponent(value || '');
      }
    }

    delete params[name];

    const newQuery = Object.entries(params)
      .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
      .join("&");

    return baseUrl + newQuery;
  }

  return undefined;
};


//判断是否是苹果还是安卓移动设备
export const isAppleMobileDevice = () => {
  let reg = /iphone|ipod|ipad|Macintosh/i;
  return reg.test(navigator.userAgent.toLowerCase());
}


//判断是否是安卓移动设备
export const isAndroidMobileDevice = () => {
  return /android/i.test(navigator.userAgent.toLowerCase());
}


//判断是否是微信/QQ内置浏览器
export const broswer = (): string | boolean => {
  const ua = navigator.userAgent.toLowerCase();
  
  if (ua.includes("micromessenger")) {
      return "weixin";
  } else if (ua.includes("qq")) {
      return "QQ";
  }
  
  return false;
};



//浏览器型号和版本

interface BrowserInfo {
  type: string;
  version: number;
}

export const getExplorerInfo = (): BrowserInfo => {
  const userAgent = navigator.userAgent.toLowerCase();
  
  if (userAgent.includes("msie")) { // IE < 11
      return {
          type: "IE",
          version: Number(userAgent.match(/msie ([\d]+)/)?.[1]) || -1
      };
  } else if (userAgent.match(/trident\/.+?rv:([\d.]+)/)) { // IE 11
      return {
          type: "IE",
          version: 11
      };
  } else if (userAgent.includes("edge")) {
      return {
          type: "Edge",
          version: Number(userAgent.match(/edge\/([\d]+)/)?.[1]) || -1
      };
  } else if (userAgent.includes("firefox")) {
      return {
          type: "Firefox",
          version: Number(userAgent.match(/firefox\/([\d]+)/)?.[1]) || -1
      };
  } else if (userAgent.includes("chrome")) {
      return {
          type: "Chrome",
          version: Number(userAgent.match(/chrome\/([\d]+)/)?.[1]) || -1
      };
  } else if (userAgent.includes("opera")) {
      return {
          type: "Opera",
          version: Number(userAgent.match(/opera.([\d]+)/)?.[1]) || -1
      };
  } else if (userAgent.includes("safari")) {
      return {
          type: "Safari",
          version: Number(userAgent.match(/version\/([\d]+)/)?.[1]) || -1
      };
  } else {
      return {
          type: userAgent,
          version: -1
      };
  }
};



//滚动到页面底部
export const scrollToBottom = ():void => {
  window.scrollTo(0, document.documentElement.clientHeight);  
}



//滚动到指定元素区域
export const smoothScroll =(element: string): void => {
  document.querySelector(element)!.scrollIntoView({
      behavior:'smooth'
  });
};


//获取可视窗口宽度
export const getClientHeight = ():number => {
  let clientHeight:number = 0;
  if (document.body.clientHeight && document.documentElement.clientHeight) {
      clientHeight = (document.body.clientHeight < document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
  }
  else {
      clientHeight = (document.body.clientHeight > document.documentElement.clientHeight) ? document.body.clientHeight : document.documentElement.clientHeight;
  }
  return clientHeight;
}


//打开浏览器全屏
export const toFullScreen = (): void => {
  const element: HTMLElement = document.body;

  if (element.requestFullscreen) {
      element.requestFullscreen();
  } else if ((element as any).mozRequestFullScreen) { // Firefox
      (element as any).mozRequestFullScreen();
  } else if ((element as any).msRequestFullscreen) { // IE/Edge
    (element as any).msRequestFullscreen();
  } else if ((element as any).webkitRequestFullscreen) { // Safari
      (element as any).webkitRequestFullscreen();
  }
};


//退出浏览器全屏
export const exitFullscreen = (): void => {
  const doc = document as Document & {
      msExitFullscreen?: () => Promise<void>;
      mozCancelFullScreen?: () => Promise<void>;
      webkitExitFullscreen?: () => Promise<void>;
  };

  if (doc.exitFullscreen) {
      doc.exitFullscreen();
  } else if (doc.msExitFullscreen) {
      doc.msExitFullscreen();
  } else if (doc.mozCancelFullScreen) {
      doc.mozCancelFullScreen();
  } else if (doc.webkitExitFullscreen) {
      doc.webkitExitFullscreen();
  }
};



//当前时间
export const nowTime = ():string => {
  const now = new Date();
  const year: number = now.getFullYear();
    const month: number = now.getMonth();
    const date: string = now.getDate() >= 10 ? now.getDate().toString() : '0' + now.getDate();
    const hour: string = now.getHours() >= 10 ? now.getHours().toString() : '0' + now.getHours();
    const miu: string = now.getMinutes() >= 10 ? now.getMinutes().toString() : '0' + now.getMinutes();
    const sec: string = now.getSeconds() >= 10 ? now.getSeconds().toString() : '0' + now.getSeconds();
  return +year + "年" + (month + 1) + "月" + date + "日 " + hour + ":" + miu + ":" + sec;
}

//阻止冒泡事件
export const stopPropagation = (e: Event | null): void => {
  e = e || window.event as Event; 

  if (e && e.stopPropagation) { 
      e.stopPropagation(); // W3C 阻止冒泡方法
  } else if (e) {
      (e as any).cancelBubble = true; // IE 阻止冒泡方法
  }
};


//数据类型判断
export const getType = (value: any): string => {
  if (value === null) {
      return value + "";
  }

  // 判断数据是引用类型的情况
  if (typeof value === "object") {
      const valueClass = Object.prototype.toString.call(value);
      const type = valueClass.split(" ")[1].split("");
      type.pop();
      return type.join("").toLowerCase();
  } else {
      // 判断数据是基本数据类型的情况和函数的情况
      return typeof value;
  }
};

